package com.taotao.container;

import com.taotao.constant.RegisterConstant;
import com.taotao.entity.ServiceInstance;
import com.taotao.rq.parameter.ReqInfoDto;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author wangjin
 * @title: SWRegisterContainer
 * @projectName sw-springcloud
 * @description: 容器存放ip和端口号
 * @date 2021/10/28 21:28
 */
@Component
public class SWRegisterContainer {
    private static volatile Map<String, HashSet<ServiceInstance>> mapserviceInstances = new ConcurrentHashMap<>();
    private static final Log log = LogFactory.getLog(SWRegisterContainer.class);
    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    public SWRegisterContainer() {
        scheduledExecutorService.scheduleAtFixedRate(new Heartbeat(), 3, 3, TimeUnit.SECONDS);

    }

    public Boolean put(ReqInfoDto reqInfoDto) {
        //判断容器是否已经注册过服务
        String serviceName = reqInfoDto.getServiceName();
        HashSet<ServiceInstance> serviceInstances = mapserviceInstances.get(serviceName);
        //注意线程安全问题
        if (serviceInstances == null) {
            //双重检验锁
            synchronized (this) {
                if (serviceInstances == null) {
                    serviceInstances = new HashSet<>();
                    mapserviceInstances.put(serviceName, serviceInstances);
                }

            }


        }
        //将接口地址存放到服务注册中心去
        ServiceInstance serviceInstance = new ServiceInstance(serviceName, reqInfoDto.getServiceAddres(), System.currentTimeMillis());
        return serviceInstances.add(serviceInstance);
    }

    public Map<String, HashSet<ServiceInstance>> getMapAddres() {
        return mapserviceInstances;
    }

    private ServiceInstance findByServiceInstance(ReqInfoDto reqInfo) {
        return findByServiceInstance(reqInfo, false);
    }

    private ServiceInstance findByServiceInstance(ReqInfoDto reqInfo, boolean isDelete) {
        String serviceAddres = reqInfo.getServiceAddres();
        if (StringUtils.isEmpty(serviceAddres)) {
            return null;
        }
        // 根据服务的名称 查找 对应 注册 多个接口地址
        HashSet<ServiceInstance> serviceInstances = mapserviceInstances.get(reqInfo.getServiceName());
        if (serviceInstances == null) {
            //没有找到服务列表
            log.error("<Service list not found>");
            return null;
        }
        // 循环遍历根据服务名称+服务地址 查找该对象
        for (ServiceInstance serviceInstance : serviceInstances) {
            if (serviceInstance.getServiceAddres().equals(serviceAddres)) {
                if (isDelete) {
                    serviceInstances.remove(serviceInstance);
                }
                return serviceInstance;
            }
        }
        return null;
    }

    /**
     * 服务移除
     *
     * @param reqInfoDto
     * @return
     */
    public ServiceInstance remove(ReqInfoDto reqInfoDto) {
        return findByServiceInstance(reqInfoDto, true);
    }

    /**
     * 服务续约
     *
     * @param
     * @return
     */
    public boolean renewal(ReqInfoDto reqInfo) {
        ServiceInstance serviceInstance = findByServiceInstance(reqInfo);
        if (serviceInstance == null) {
            //在做服务续约时 发现容器中没有该服务
            return put(reqInfo);
        }
        //最后续约时间+5000毫秒
        serviceInstance.setLastRenewalTime(serviceInstance.getLastRenewalTime() + reqInfo.getRenewalDuration());
        return true;
    }

    /**
     * 注册中心 心测检测线程
     */
    class Heartbeat implements Runnable {

        @Override
        public void run() {
            //遍历容器
            mapserviceInstances.forEach((k, v) -> {
                //取出每个服务对应的集群；
                HashSet<ServiceInstance> serviceInstances = mapserviceInstances.get(k);
                serviceInstances.forEach((serviceInstance -> {
                    if (System.currentTimeMillis() - serviceInstance.getLastRenewalTime() > RegisterConstant.DELETEIP_TIMEOUT) {
                        // 3.系统时间-该接口地址最后续约时间>10s
                        // 续约时间  22:00:10
                        long currentTimeMillis = System.currentTimeMillis();
                        long lastRenewalTime = serviceInstance.getLastRenewalTime();
                        if (currentTimeMillis - lastRenewalTime > RegisterConstant.DELETEIP_TIMEOUT) {
                            log.info("服务名称：" + serviceInstance.getServiceName() + "," +
                                    "服务地址" + serviceInstance.getServiceAddres() + ",当前系统时间:" + currentTimeMillis
                                    + ",该服务上一次续约时间" + lastRenewalTime + "服务被剔除.");

                            //续约超时，直接移除 剔除该地址
                        }
                        serviceInstances.remove(serviceInstance);
                    }
                    ;
                }));
            });
        }
    }
}
